/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.esigate.xml; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.Writer; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import nu.validator.htmlparser.common.DoctypeExpectation; import nu.validator.htmlparser.dom.Dom2Sax; import nu.validator.htmlparser.dom.HtmlDocumentBuilder; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.esigate.Driver; import org.esigate.HttpErrorPage; import org.esigate.Renderer; import org.esigate.http.HttpResponseUtils; import org.esigate.impl.DriverRequest; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Applies an XSLT transformation to the retrieved data. * * If no namespace is specified in the document to transform, it is asumed as:<br /> * xmlns="http://www.w3.org/1999/xhtml" * * @author Stanislav Bernatskyi * @author Francois-Xavier Bonnet */ public class XsltRenderer implements Renderer { private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); private Transformer transformer; /** * @param template * The path to the xsl template, relative to the context root * @param driver * driver * @param originalRequest * @throws IOException * If an error occurs while writing to the output * @throws HttpErrorPage */ public XsltRenderer(String template, Driver driver, DriverRequest originalRequest) throws IOException, HttpErrorPage { StringBuilder templateStringBuilder = new StringBuilder(); CloseableHttpResponse response = driver.render(template, originalRequest.getOriginalRequest()); templateStringBuilder.append(HttpResponseUtils.toString(response)); transformer = createTransformer(IOUtils.toInputStream(templateStringBuilder)); } /** * @param xsl * The xsl template to apply as a String * @throws IOException * If an error occurs while writing to the output */ public XsltRenderer(String xsl) throws IOException { InputStream templateStream = IOUtils.toInputStream(xsl); transformer = createTransformer(templateStream); } private static Transformer createTransformer(InputStream templateStream) throws IOException { try { return TRANSFORMER_FACTORY.newTransformer(new StreamSource(templateStream)); } catch (TransformerConfigurationException e) { throw new ProcessingFailedException("Failed to create XSLT template", e); } finally { templateStream.close(); } } /** {@inheritDoc} */ @Override public void render(DriverRequest httpRequest, String src, Writer out) throws IOException { try { HtmlDocumentBuilder htmlDocumentBuilder = new HtmlDocumentBuilder(); htmlDocumentBuilder.setDoctypeExpectation(DoctypeExpectation.NO_DOCTYPE_ERRORS); Document document = htmlDocumentBuilder.parse(new InputSource(new StringReader(src))); Source source = new DOMSource(document); DOMResult result = new DOMResult(); transformer.transform(source, result); XhtmlSerializer serializer = new XhtmlSerializer(out); Dom2Sax dom2Sax = new Dom2Sax(serializer, serializer); dom2Sax.parse(result.getNode()); } catch (TransformerException e) { throw new ProcessingFailedException("Failed to transform source", e); } catch (SAXException e) { throw new ProcessingFailedException("Failed serialize transformation result", e); } } }